package com.example.bankingsystemandroid;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.TimeZone;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONTokener;

import android.app.Dialog;
import android.app.Fragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.ExpandableListView;
import android.widget.Toast;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.csc.bankingsystem.core.dto.TransferRecordDTO;
import com.example.bankingsystemandroid.Holder.InfoHolder;
import com.example.bankingsystemandroid.adapter.ExpandableListAdapter;
import com.example.bankingsystemandroid.utils.PropertiesConfig;
import com.example.bankingsystemandroid.utils.PropertyManager;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;

public class TransactionFragment extends Fragment {
	ExpandableListAdapter listAdapter;
	ExpandableListView transListView;
	List<String> listDataHeader = new ArrayList<String>();
	HashMap<String, List<TransferRecordDTO>> listDataChild = new HashMap<String, List<TransferRecordDTO>>();
	ArrayList<NameValuePair> postParameters;
	private ProgressBar mProgress;
	View layout;
	boolean loadingMore = false;
	String lastItem;
	Button btnLoadMore;
	boolean flagAllRecordLoaded = false;

	public TransactionFragment() {
		InfoHolder.getTransferRecordList().clear();
		postParameters = new ArrayList<NameValuePair>();
		postParameters.add(new BasicNameValuePair("firstResult", "0"));
		postParameters.add(new BasicNameValuePair("pageSize", "2"));
		postParameters.add(new BasicNameValuePair("datetimeStr", ""));

		GetTransferRecordTask getTransferRecordTask = new GetTransferRecordTask();
		getTransferRecordTask.execute(postParameters);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {

		View v = inflater.inflate(R.layout.fragment_transaction, container,
				false);
		layout = v.findViewById(R.id.layout_transaction_fragment);
		super.onCreate(savedInstanceState);

		mProgress = (ProgressBar) v
				.findViewById(R.id.progress_bar_fragmen_transaction);
		mProgress.bringToFront();
		mProgress.setIndeterminate(true);
		mProgress.setVisibility(View.VISIBLE);
		layout.setVisibility(View.INVISIBLE);

		btnLoadMore = (Button) v.findViewById(R.id.btnLoadMore);
		btnLoadMore.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if (!loadingMore) {
					// load more
					// String index = new String();
					postParameters = new ArrayList<NameValuePair>();
					int nextIndex = InfoHolder.getTransferRecordList().size() + 1;
					postParameters.add(new BasicNameValuePair("firstResult", ""
							+ nextIndex));
					postParameters.add(new BasicNameValuePair("pageSize", "2"));
					postParameters.add(new BasicNameValuePair("datetimeStr",
							lastItem));

					GetTransferRecordTask getTransferRecordTask = new GetTransferRecordTask();
					getTransferRecordTask.execute(postParameters);
					loadingMore = true;
				}
			}
		});
		// get the listview
		transListView = (ExpandableListView) layout
				.findViewById(R.id.transListView);
		// transListView.setOnScrollListener(new OnScrollListener(){
		//
		// @Override
		// public void onScrollStateChanged(AbsListView view, int scrollState) {
		//
		// }
		//
		// @Override
		// public void onScroll(AbsListView view, int firstVisibleItem,
		// int visibleItemCount, int totalItemCount) {
		//
		// int lastInScreen = firstVisibleItem + visibleItemCount;
		// if((lastInScreen == totalItemCount) && !(loadingMore)) {
		//
		// }
		// }
		// });
		return v;

	}

	public void initView() {
		// preparing list data
		// prepareListData();

		listAdapter = new ExpandableListAdapter(getActivity().getBaseContext(),
				listDataHeader, listDataChild);

		// setting list adapter
		transListView.setAdapter(listAdapter);

		// Listview Group click listener
		transListView.setOnGroupClickListener(new OnGroupClickListener() {

			@Override
			public boolean onGroupClick(ExpandableListView parent, View v,
					int groupPosition, long id) {
				return false;
			}
		});

		// Listview Group expanded listener
		transListView.setOnGroupExpandListener(new OnGroupExpandListener() {

			@Override
			public void onGroupExpand(int groupPosition) {
			}
		});

		// Listview Group collasped listener
		transListView.setOnGroupCollapseListener(new OnGroupCollapseListener() {

			@Override
			public void onGroupCollapse(int groupPosition) {

			}
		});

		// Listview on child click listener
		transListView.setOnChildClickListener(new OnChildClickListener() {

			@Override
			public boolean onChildClick(ExpandableListView parent, View v,
					int groupPosition, int childPosition, long id) {
				// custom dialog
				final Dialog dialog = new Dialog(getActivity());
				SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
				sdf.setLenient(false);
				dialog.setContentView(R.layout.transfer_detail);
				dialog.setTitle("Transfer detail");
				TransferRecordDTO dto = (TransferRecordDTO) ((ExpandableListAdapter) transListView
						.getExpandableListAdapter()).getChild(groupPosition,
						childPosition);
				TextView time = (TextView) dialog
						.findViewById(R.id.time_transfer_detail_fragment);
				TextView source = (TextView) dialog
						.findViewById(R.id.source_transfer_detail_fragment);
				TextView destination = (TextView) dialog
						.findViewById(R.id.destination_transfer_detail_fragment);
				TextView amount = (TextView) dialog
						.findViewById(R.id.amount_transfer_detail_fragment);
				TextView unit = (TextView) dialog
						.findViewById(R.id.unit_transfer_detail_fragment);
				TextView message = (TextView) dialog
						.findViewById(R.id.message_transfer_detail_fragment);
				TextView status = (TextView) dialog
						.findViewById(R.id.status_transfer_detail_fragment);
				TextView remain = (TextView) dialog
						.findViewById(R.id.remain_transfer_detail_fragment);

				source.setText(dto.getSourceAccountNumber());
				destination.setText(dto.getDestinationAccountNumber());
				amount.setText(dto.getAmount().toString());
				unit.setText(dto.getUnit());
				message.setText(dto.getMessage());
				status.setText(dto.getStatus());
				remain.setText(dto.getRemainAmount().toString());
				time.setText(sdf.format(dto.getTransDate()));

				Button btnOk = (Button) dialog
						.findViewById(R.id.btnOk_transfer_detail_fragment);
				btnOk.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						dialog.dismiss();
					}
				});

				dialog.show();
				return false;

			}
		});
	}

	public class GetTransferRecordTask extends
			AsyncTask<ArrayList<NameValuePair>, Void, Void> {

		@Override
		protected void onPostExecute(Void result) {
			prepareListData();
			if (!loadingMore) {
				// First Time load
				initView();
				lastItem = fromDateTime(InfoHolder.getTransferRecordList()
						.get(0).getTransDate());
			}
			loadingMore = false;
			listAdapter.notifyDataSetChanged();

			if (mProgress.getVisibility() == View.VISIBLE) {
				mProgress.setVisibility(View.GONE);
			}
			if (layout.getVisibility() == View.INVISIBLE) {
				layout.setVisibility(View.VISIBLE);
			}
			if (flagAllRecordLoaded) {
				Toast.makeText(getActivity(), "All records are loaded",
						Toast.LENGTH_SHORT).show();
			}
			super.onPostExecute(result);
		}

		@Override
		protected Void doInBackground(ArrayList<NameValuePair>... params) {
			/*
			 * Create the POST request
			 */
			HttpClient httpClient = new DefaultHttpClient();
			String serverIP = PropertiesConfig
					.getProperty(PropertyManager.SERVER_IP);
			String serverPort = PropertiesConfig
					.getProperty(PropertyManager.SERVER_PORT);
			HttpPost httpPost = new HttpPost("http://" + serverIP + ":"
					+ serverPort + "/bankingsystem/api/get-transfer-records");
			// Request parameters and other properties.

			try {
				httpPost.setEntity(new UrlEncodedFormEntity(params[0]));
			} catch (UnsupportedEncodingException e2) {
				e2.printStackTrace();
			}
			/*
			 * Execute the HTTP Request
			 */
			try {
				httpPost.addHeader("Cookie",
						"JSESSIONID=" + InfoHolder.getSessionId());
				HttpResponse response = httpClient.execute(httpPost);
				HttpEntity respEntity = response.getEntity();

				if (response != null) {
					BufferedReader reader = new BufferedReader(
							new InputStreamReader(respEntity.getContent(),
									"UTF-8"));

					StringBuilder builder = new StringBuilder();
					for (String line = null; (line = reader.readLine()) != null;) {
						builder.append(line).append("\n");
					}
					JSONTokener tokener = new JSONTokener(builder.toString());
					JSONArray finalResult = new JSONArray(tokener);

					ArrayList<TransferRecordDTO> transferRecordDTOs = new ArrayList<TransferRecordDTO>();

					Gson gson = new GsonBuilder().registerTypeAdapter(
							Date.class, new JsonDateDeserializer()).create();
					// Gson gson = new Gson();
					Type collectionType = new TypeToken<ArrayList<TransferRecordDTO>>() {
					}.getType();
					transferRecordDTOs = gson.fromJson(finalResult.toString(),
							collectionType);
					if (transferRecordDTOs == null
							|| transferRecordDTOs.size() == 0) {
						flagAllRecordLoaded = true;
					} else {
						InfoHolder.getTransferRecordList().addAll(
								transferRecordDTOs);
						// InfoHolder.setTransferRecordList(transferRecordDTOs);
					}
				}
			} catch (ClientProtocolException e) {
				// writing exception to log
				e.printStackTrace();
			} catch (IOException e) {
				// writing exception to log
				e.printStackTrace();
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}

	}

	private class JsonDateDeserializer implements JsonDeserializer<Date> {
		public Date deserialize(JsonElement json, Type typeOfT,
				JsonDeserializationContext context) throws JsonParseException {
			Calendar cal = Calendar.getInstance(TimeZone
					.getTimeZone("Asia/Saigon"));
			cal.setTimeInMillis(json.getAsJsonPrimitive().getAsLong());
			cal.setTimeZone(TimeZone.getTimeZone("Asia/Saigon"));
			cal.add(Calendar.HOUR_OF_DAY, 7);
			Date d = cal.getTime();
			return d;
		}
	}

	private String fromDate(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		sdf.setLenient(false);
		return sdf.format(date);
	}

	private String fromDateTime(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS");
		sdf.setLenient(false);
		return sdf.format(date);
	}

	/*
	 * Preparing the list data
	 */
	private void prepareListData() {
		listDataHeader.clear();
		listDataChild.clear();
		ArrayList<ArrayList<TransferRecordDTO>> arrayList = new ArrayList<ArrayList<TransferRecordDTO>>();
		// Adding header data
		boolean flagDoNotBelongAnyDate;
		for (TransferRecordDTO dto : InfoHolder.getTransferRecordList()) {
			String tempDate1 = fromDate(dto.getTransDate());
			flagDoNotBelongAnyDate = true;
			for (ArrayList<TransferRecordDTO> innerDateList : arrayList) {
				String tempDate2 = fromDate(innerDateList.get(0).getTransDate());
				if (tempDate1.compareTo(tempDate2) == 0) {
					innerDateList.add(dto);
					flagDoNotBelongAnyDate = false;
					break;
				}
			}
			if (flagDoNotBelongAnyDate) {
				ArrayList<TransferRecordDTO> innerDateList = new ArrayList<TransferRecordDTO>();
				innerDateList.add(dto);
				arrayList.add(innerDateList);
			}
		}

		for (ArrayList<TransferRecordDTO> dateList : arrayList) {
			String tempDate = fromDate(dateList.get(0).getTransDate());
			listDataHeader.add(tempDate);
			List<TransferRecordDTO> listRecord = new ArrayList<TransferRecordDTO>();
			listRecord.addAll(dateList);
			listDataChild.put(tempDate, listRecord);
		}
	}
}